﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using SqlOrm.Xml;
using System.IO;

namespace SqlOrm.ScriptBuilder
{
    public class ScriptBuilderFactory
    {
        readonly DataDictionary _ddl;
        readonly string _xmlpath;
        public ScriptBuilderFactory(string xmlpath, DataDictionary ddl)
        {
            _xmlpath = xmlpath;
            _ddl = ddl;
        }

        IScriptBuilder GetScriptBuilder()
        {
            IScriptBuilder result=null;
            if (_ddl.Settings.Database.ver == DatabaseVersion.Sql2008R2)
                return (IScriptBuilder)new SQL2008R2ScriptBuilder { DDL = _ddl };
            else if (_ddl.Settings.Database.ver == DatabaseVersion.SqlCompact35)
                return (IScriptBuilder)new SQLCompact35ScriptBuilder { DDL = _ddl };
            return result;
        }

        public void Build()
        {
            int d = 0;
            var script = GetScriptBuilder();
            string tmpfile = Path.GetTempFileName();
            using (var sw = new StreamWriter(tmpfile))
            {
                script.UseDatabase(sw, d);
                script.DropConstraints(sw, d);
                script.DropIndeces(sw, d);
                script.DropTables(sw, d);
                script.CreateTables(sw, d);
                script.CreateIndeces(sw, d);
                script.CreateConstraints(sw, d);
                sw.Flush();
            }
            Move(_ddl.Settings.ScriptOutput.path + "\\struct.sql", tmpfile);
            tmpfile = Path.GetTempFileName();
            using (var sw = new StreamWriter(tmpfile))
            {
                script.UseDatabase(sw, d);
                script.DropProcs(sw, d);
                script.CreateUpsertProcs(sw, d);
                script.CreateInsertProcs(sw, d);
                script.CreateGetProcs(sw, d);
                script.CreateDeleteProcs(sw, d);
                script.CreateSearchProcs(sw, d);
                script.CreateAllProcs(sw, d);
                script.CreateCustomProcs(sw, d);
                sw.Flush();
            }
            Move(_ddl.Settings.ScriptOutput.path + "\\proc.sql", tmpfile);
        }

        public void Move(string path, string tmpfile)
        {
            string fullpath = Program.CombinePath(_xmlpath, path);
            if (File.Exists(fullpath))
                File.Delete(fullpath);
            File.Move(tmpfile, fullpath);
        }
    }

    public interface IScriptBuilder
    {
        DataDictionary DDL { get; set; }
        void UseDatabase(StreamWriter sw, int d);
        void DropConstraints(StreamWriter sw, int d);
        void DropTables(StreamWriter sw, int d);
        void CreateTables(StreamWriter sw, int d);
        void CreateConstraints(StreamWriter sw, int d);
        void CreateIndeces(StreamWriter sw, int d);
        void DropIndeces(StreamWriter sw, int d);

        void DropProcs(StreamWriter sw, int d);
        void CreateUpsertProcs(StreamWriter sw, int d);
        void CreateInsertProcs(StreamWriter sw, int d);
        void CreateGetProcs(StreamWriter sw, int d);
        void CreateDeleteProcs(StreamWriter sw, int d);
        void CreateSearchProcs(StreamWriter sw, int d);
        void CreateAllProcs(StreamWriter sw, int d);
        void CreateCustomProcs(StreamWriter sw, int d);
    }
}
